package edu.hitsz.application;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.*;
import javax.sound.sampled.DataLine.Info;

public class MusicThread extends Thread {

    public static String bgm = "src/videos/bgm.wav";
    public static String bgmBoss = "src/videos/bgm_boss.wav";
    public static String bombExplosion = "src/videos/bomb_explosion.wav";
    public static String bullet = "src/videos/bullet.wav";
    public static String bulletHit = "src/videos/bullet_hit.wav";
    public static String gameOver = "src/videos/game_over.wav";
    public static String getSupply = "src/videos/get_supply.wav";

    //音频是否循环播放
    private boolean isLoop = false;

    //音频是否继续播放
    private boolean isPlay = true;

    //音频文件名
    private String filename;
    private AudioFormat audioFormat;
    private byte[] samples;
    private double value;

    public void setLoop(boolean loop) {
        isLoop = loop;
    }

    public void setPlay(boolean play) {
        isPlay = play;
    }

    public MusicThread(String filename) {
        //初始化filename
        this.filename = filename;
        reverseMusic();
        if (this.filename.equals(bombExplosion)) {
            this.value = 0.08;
        }
    }

    public void reverseMusic() {
        try {
            //定义一个AudioInputStream用于接收输入的音频数据，使用AudioSystem来获取音频的音频输入流
            AudioInputStream stream = AudioSystem.getAudioInputStream(new File(filename));
            //用AudioFormat来获取AudioInputStream的格式
            audioFormat = stream.getFormat();
            samples = getSamples(stream);
        } catch (UnsupportedAudioFileException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public byte[] getSamples(AudioInputStream stream) {
        int size = (int) (stream.getFrameLength() * audioFormat.getFrameSize());
        byte[] samples = new byte[size];
        DataInputStream dataInputStream = new DataInputStream(stream);
        try {
            dataInputStream.readFully(samples);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return samples;
    }

    public void play(InputStream source) {
        int size = (int) (audioFormat.getFrameSize() * audioFormat.getSampleRate());
        byte[] buffer = new byte[size];
        //源数据行SoureDataLine是可以写入数据的数据行
        SourceDataLine dataLine = null;
        //获取受数据行支持的音频格式DataLine.info
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
        try {
            dataLine = (SourceDataLine) AudioSystem.getLine(info);
            dataLine.open(audioFormat, size);
        } catch (LineUnavailableException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        dataLine.start();

        if (this.filename.equals(bombExplosion)) {
            FloatControl control = (FloatControl) dataLine.getControl(FloatControl.Type.MASTER_GAIN);
            float dB = (float)(Math.log(value == 0.0 ? 0.0001 : value) / Math.log(10.0) * 20.0);
            control.setValue((float)(dB));
        }

        try {
            int numBytesRead = 0;
            while (numBytesRead != -1) {
                if(!isPlay){
                    break;
                }
				//从音频流读取指定的最大数量的数据字节，并将其放入缓冲区中
                numBytesRead =
                        source.read(buffer, 0, buffer.length);
				//通过此源数据行将数据写入混频器
                if (numBytesRead != -1) {
                    dataLine.write(buffer, 0, numBytesRead);
                }
            }

        } catch (IOException ex) {
            ex.printStackTrace();
        }

        dataLine.drain();
        dataLine.close();

    }

    @Override
    public void run() {
        do{
            InputStream stream = new ByteArrayInputStream(samples);
            play(stream);
        } while (isLoop);
    }
}